package com.ctshk.rpc.finance.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.SysApprovalType;
import com.ctshk.common.enums.SystemBusinessType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.finance.dto.bill.CheckAmountStaticsDTO;
import com.ctshk.rpc.finance.dto.onaccount.OffAccountApplyDTO;
import com.ctshk.rpc.finance.dto.onaccount.OffAccountApplyDetailDTO;
import com.ctshk.rpc.finance.dto.onaccount.OffAccountListDTO;
import com.ctshk.rpc.finance.dto.onaccount.OffAccountUsedListDTO;
import com.ctshk.rpc.finance.entity.*;
import com.ctshk.rpc.finance.json.FileJson;
import com.ctshk.rpc.finance.json.OffAccountAmountJson;
import com.ctshk.rpc.finance.mapper.*;
import com.ctshk.rpc.finance.req.onaccount.*;
import com.ctshk.rpc.finance.service.IFinanceOffAccountApplyService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 财务销账申请记录 服务实现类
 * </p>
 *
 * @author 叶冠峰
 * @since 2021-03-31
 */
@DubboService
public class FinanceOffAccountApplyServiceImpl extends ServiceImpl<FinanceOffAccountApplyMapper, FinanceOffAccountApply> implements IFinanceOffAccountApplyService {

    @Autowired
    private FinanceOffAccountApplyMapper offAccountApplyMapper;
    @Autowired
    private FinanceOffAccountApplyDetailMapper offAccountApplyDetailMapper;
    @Autowired
    private FinanceOnAccountMapper onAccountMapper;
    @Autowired
    private FinanceBillMapper billMapper;
    @Autowired
    private FinanceAdvancePaymentApplySummaryMapper advancePaymentApplySummaryMapper;
    @Autowired
    private FinanceOnAccountCurrencyQuotaMapper onAccountCurrencyQuotaMapper;
    @Autowired
    private FinanceOnAccountUsageRecordMapper onAccountUsageRecordMapper;

    @DubboReference
    private ISysApprovalService sysApprovalService;
    @DubboReference
    private ISysUserService sysUserService;


    /**
     * 申请销账
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(OffAccountAddReq req) {
        if (req.getBillIdList().size() == 0){
            throw new BusinessException(SystemError.SYS_402);
        }
        //获取挂账单
        FinanceOnAccount account = onAccountMapper.selectById(req.getOnAccountId());
        if (account == null || Objects.equals(account.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17013);
        }
        //销账申请
        FinanceOffAccountApply apply = EntityUtil.copy(req,FinanceOffAccountApply.class);
        LocalDateTime now = LocalDateTime.now();
        apply.setId(SnowflakeIdWorker.nextId());
        apply.setCreateId(req.getUserId());
        apply.setGmtCreate(now);
        apply.setIsDeleted(0);
        List<FinanceOffAccountApplyDetail> applyDetailList = new ArrayList<>();
        //挂账使用记录
        List<FinanceOnAccountUsageRecord> recordList = onAccountUsageRecordMapper.selectBatchIds(req.getBillIdList());
        if (CollectionUtils.isNotEmpty(recordList)){
            recordList.forEach(record -> {
                //销账明细
                FinanceOffAccountApplyDetail applyDetail = EntityUtil.copy(record,FinanceOffAccountApplyDetail.class);
                applyDetail.setId(SnowflakeIdWorker.nextId());
                applyDetail.setBillId(record.getId());
                applyDetail.setApplyId(apply.getId());
                applyDetail.setOnAccountId(req.getOnAccountId());
                applyDetail.setCreateId(req.getUserId());
                applyDetail.setGmtCreate(now);
                applyDetail.setIsDeleted(0);
                applyDetailList.add(applyDetail);
            });
        }
        //币种金额统计
        List<CheckAmountStaticsDTO> staticsDTOList = billMapper.sumCurrencyStaticsByBatchId(req.getBillIdList());
        if (staticsDTOList != null && staticsDTOList.size() > 0){
            List<OffAccountAmountJson> amountJson = new ArrayList<>();
            staticsDTOList.forEach(statics -> {
                if (statics.getCollectAmount() == null){
                    statics.setCollectAmount(BigDecimal.ZERO);
                }
                if (statics.getRefundAmount() == null){
                    statics.setRefundAmount(BigDecimal.ZERO);
                }
                BigDecimal resultAmount = statics.getCollectAmount().subtract(statics.getRefundAmount());
                statics.setResultAmount(resultAmount);
                statics.setType(resultAmount.compareTo(BigDecimal.ZERO) >= 0?1:2);
                OffAccountAmountJson accountAmountJson = EntityUtil.copy(statics,OffAccountAmountJson.class);
                amountJson.add(accountAmountJson);
            });
            String amountJsonStr = JSON.toJSONString(amountJson);
            apply.setAmountJson(amountJsonStr);
        }
        //新增销账申请
        boolean save = save(apply);
        if (!save){
            throw new BusinessException(SystemError.SYS_437);
        }
        //批量新增销账明细
        if (applyDetailList.size() > 0){
            Integer batch = offAccountApplyDetailMapper.insertBatchSomeColumn(applyDetailList);
            if (batch < applyDetailList.size()){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        //发起审批
        Long approvalId = startApproval(apply.getId(), apply.getId(), req.getUserId());
        apply.setApprovalId(approvalId);
        apply.setApprovalStatus(2);
        boolean update = updateById(apply);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(apply.getId());
    }

    /**
     * 列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<List<OffAccountListDTO>> list(OffnAccountListReq req) {
        List<OffAccountListDTO> list = new ArrayList<>();
        QueryWrapper<FinanceOffAccountApply> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("on_account_id",req.getOnAccountId());
        queryWrapper.eq("is_deleted",0);
        List<FinanceOffAccountApply> applyList = offAccountApplyMapper.selectList(queryWrapper);
        if (applyList != null && applyList.size() > 0){
            applyList.forEach(apply -> {
                OffAccountListDTO dto = EntityUtil.copy(apply,OffAccountListDTO.class);
                if (StringUtils.isNotBlank(apply.getAmountJson())){
                    //金额JSON
                    List<OffAccountAmountJson> amountJsons = JSON.parseArray(apply.getAmountJson(), OffAccountAmountJson.class);
                    dto.setAmountJson(amountJsons);
                }
                if (StringUtils.isNotBlank(apply.getCollectionFilesJson())){
                    //收款凭证JSON
                    List<FileJson> fileJson = JSON.parseArray(apply.getCollectionFilesJson(), FileJson.class);
                    dto.setCollectionFilesJson(fileJson);
                }
                //申请人
                UserDTO userDto = sysUserService.queryCacheUser(apply.getCreateId());
                if (userDto != null){
                    dto.setApplyUserName(userDto.getFullName());
                    dto.setApplyUserDept(userDto.getDept());
                }
                list.add(dto);
            });
        }
        return Result.success(list);
    }

    /**
     * 详情
     *
     * @param req
     * @return
     */
    @Override
    public Result<OffAccountApplyDTO> detail(OffAccountIdReq req) {
        //查询销账申请
        FinanceOffAccountApply apply = getById(req.getId());
        if (apply == null || Objects.equals(apply.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17015);
        }
        //查询挂账信息
        FinanceOnAccount account = onAccountMapper.selectById(apply.getOnAccountId());
        if (account == null || Objects.equals(account.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17013);
        }
        //返回数据
        OffAccountApplyDTO dto = EntityUtil.copy(apply,OffAccountApplyDTO.class);
        if (StringUtils.isNotBlank(apply.getCollectionFilesJson())){
            //收款凭证JSON
            List<FileJson> fileJsons = JSON.parseArray(apply.getCollectionFilesJson(), FileJson.class);
            dto.setCollectionFilesJson(fileJsons);
        }
        if (StringUtils.isNotBlank(apply.getAmountJson())){
            //金额JSON
            List<OffAccountAmountJson> amountJsons = JSON.parseArray(apply.getAmountJson(), OffAccountAmountJson.class);
            dto.setAmountJson(amountJsons);
        }
        //申请人
        UserDTO userDto = sysUserService.queryCacheUser(apply.getCreateId());
        if (userDto != null){
            dto.setApplyUserName(userDto.getFullName());
            dto.setApplyUserDept(userDto.getDept());
        }
        //销账明细列表
        QueryWrapper<FinanceOffAccountApplyDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("apply_id",apply.getId());
        queryWrapper.eq("is_deleted",0);
        List<FinanceOffAccountApplyDetail> detailList = offAccountApplyDetailMapper.selectList(queryWrapper);
        if (detailList != null && detailList.size() > 0){
            List<OffAccountApplyDetailDTO> detailDTOList = new ArrayList<>();
            detailList.forEach(detail -> {
                OffAccountApplyDetailDTO detailDTO = EntityUtil.copy(detail,OffAccountApplyDetailDTO.class);
                //销售
                UserDTO salerDto = sysUserService.queryCacheUser(detail.getSaleUserId());
                if (salerDto != null){
                    detailDTO.setSaleUserDept(salerDto.getDept());
                }
                detailDTOList.add(detailDTO);
            });
            dto.setDetailList(detailDTOList);
        }
        return Result.success(dto);
    }

    /**
     * 审批
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result approval(OffAccountApprovalReq req) {
        QueryWrapper<FinanceOffAccountApply> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("approval_id",req.getApprovalId());
        queryWrapper1.eq("is_deleted",0);
        FinanceOffAccountApply apply = offAccountApplyMapper.selectOne(queryWrapper1);
        if (apply == null){
            throw new BusinessException(SystemError.FINANCE_BILL_17015);
        }
        if (!Objects.equals(apply.getApprovalStatus(),2)){
            throw new BusinessException(SystemError.FINANCE_BILL_17012);
        }
        apply.setApprovalStatus(req.getType());
        apply.setModifiedId(req.getUserId());
        boolean update = updateById(apply);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        List<OffAccountAmountJson> amountJsons = JSON.parseArray(apply.getAmountJson(), OffAccountAmountJson.class);
        if (Objects.equals(req.getType(),3)){
            //审批通过
            if (Objects.equals(apply.getUseAdvanceMoney(),1)){
                //使用预收款
                FinanceOnAccount account = onAccountMapper.selectById(apply.getOnAccountId());
                if (account != null){
                    if (amountJsons != null && amountJsons.size() > 0){
                        amountJsons.forEach(json -> {
                            QueryWrapper<FinanceAdvancePaymentApplySummary> queryWrapper = new QueryWrapper<>();
                            queryWrapper.eq("supplier_id",account.getAccountId());
                            queryWrapper.eq("currency_id",json.getCurrencyId());
                            queryWrapper.eq("is_deleted",0);
                            FinanceAdvancePaymentApplySummary summary = advancePaymentApplySummaryMapper.selectOne(queryWrapper);
                            if (summary != null){
                                summary.setAmountUsed(summary.getAmountUsed().add(json.getResultAmount()));
                                summary.setRemainingAmount(summary.getRemainingAmount().subtract(json.getResultAmount()));
                                summary.setAvailableAmount(summary.getAvailableAmount().subtract(json.getResultAmount()));
                                summary.setModifiedId(req.getUserId());
                                int updateById = advancePaymentApplySummaryMapper.updateById(summary);
                                if (updateById <= 0){
                                    throw new BusinessException(SystemError.SYS_437);
                                }
                            }
                        });
                    }
                }
            }
            if (Objects.equals(apply.getIsReturnAmount(),1)){
                //返还额度
                if (amountJsons != null && amountJsons.size() > 0){
                    amountJsons.forEach(json -> {
                        QueryWrapper<FinanceOnAccountCurrencyQuota> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("on_account_id",apply.getOnAccountId());
                        queryWrapper.eq("currency_id",json.getCurrencyId());
                        queryWrapper.eq("is_deleted",0);
                        FinanceOnAccountCurrencyQuota quota = onAccountCurrencyQuotaMapper.selectOne(queryWrapper);
                        if (quota != null){
                            quota.setWriteOffAmount(quota.getWriteOffAmount().add(json.getResultAmount()));
                            quota.setModifiedId(req.getUserId());
                            int updateById = onAccountCurrencyQuotaMapper.updateById(quota);
                            if (updateById <= 0){
                                throw new BusinessException(SystemError.SYS_437);
                            }
                        }
                    });
                }
            }
        }
        Result<ApprovalCheckDTO> check = sysApprovalService.check(req.getApprovalId(), req.getUserId(), req.getType(), req.getComments());
        if (check == null || !check.getData().getIsFinish()){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(apply.getId());
    }

    /**
     * 预收明细-使用记录
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<OffAccountUsedListDTO>> usedList(OffAccountUsedListReq req) {
        Page<OffAccountUsedListDTO> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        Page<OffAccountUsedListDTO> page = offAccountApplyMapper.queryUsedListByOnAccountId(req.getAccountId(),iPage);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        page.getRecords().forEach(dto -> {
            //申请人部门
            UserDTO userDTO = sysUserService.queryCacheUser(dto.getCreateId());
            if (userDTO != null){
                dto.setApplyUserName(userDTO.getFullName());
                dto.setApplyUserDept(userDTO.getDept());
            }
        });
        PageResponse<OffAccountUsedListDTO> result = new PageResponse<>(
                page.getRecords(),
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }


    /**
     * 发起审批流程
     * @param id
     * @param businessId
     * @param userId
     */
    private Long startApproval(Long id, Long businessId, Long userId) {
        Map<String, Object> extendParams = new HashMap<>();
        extendParams.put("id", id);
        try{
            Result<ApprovalStartDTO> approvalResult = sysApprovalService.start(SystemBusinessType.FINANCE.getCode(),
                    SysApprovalType.CANCELACC_CANCELACC_FINANCE.getCode(), businessId,
                    userId, null, JSON.toJSONString(extendParams));
            if (!approvalResult.isSuccess()) {
                throw new BusinessException(SystemError.CUSTOM_ORDER_4044);
            }
            return approvalResult.getData().getApprovalId();
        }catch (Exception e){
            throw new BusinessException(SystemError.SYS_422);
        }
    }



}
